# -*- coding: iso8859-1 -*-
#
# Copyright (C) 2005 CSIRO Australia All rights reserved.
#
# This software is licensed as described in the file COPYING, which you should
# have received as part of this distribution.
#
# This software consists of voluntary contributions made by many individuals.
# For exact contribution history, see the revision history and logs.
#
# Author: Conrad Parker <conrad@annodex.net>

# This class is originally from cmmliki. Modified very slightly for use in
# arkaiv by Denis Crowdy

import sys
import os
import shutil

# Depends on GStreamer 0.10
# Set to False if gst0.10 is not available, in which case it will
# fall back to mplayer (which must be installed and capable of decoding
# theora and generating png).
# GStreamer tends to have more accurate frame seeking, hence it is
# enabled by default.
#FIXME: does not return an image if seeking beond eof
#use_gst=True

default_width=60

class snapshot_gst:
    getShot = False
    def __init__ (self, source, png_frame, seconds):
        global Image, pygst, gst
        import gobject
        gobject.threads_init ()
        import Image
        import pygst
        pygst.require('0.10')
        import gst

        self.png_frame = png_frame

        nseconds = int(seconds * gst.SECOND)
        s = '''filesrc name=input 
             ! decodebin name=dbin 
             ! queue name=q
             ! ffmpegcolorspace ! video/x-raw-rgb 
             ! fakesink name=output signal-handoffs=true'''
        pipeline = gst.parse_launch (s)

        input  = pipeline.get_by_name ('input')
        input.set_property ("location", source)

        output = pipeline.get_by_name ('output')
        output.connect ("handoff", self.snapshot_handoff_cb)
    
        pipeline.set_state (gst.STATE_PAUSED)
        pipeline.get_state ()

        #length
        length = 0
        queue = pipeline.get_by_name('q')
        pads = queue.sink_pads()
        q = gst.query_new_duration(gst.FORMAT_TIME)
        for pad in pads:
          if pad.get_peer() and pad.get_peer().query(q):
            format, length = q.parse_duration()

        #show first frame if seekpoint is higher than length
        if(length and length < nseconds):
            nseconds = 0

        #seek
        event = gst.event_new_seek(1.0, gst.FORMAT_TIME,
                gst.SEEK_FLAG_FLUSH,
                gst.SEEK_TYPE_SET, nseconds,
                gst.SEEK_TYPE_NONE, 0)
        res = output.send_event(event)
        if res:
            pipeline.set_new_stream_time(0L)

        pipeline.set_state (gst.STATE_PLAYING)
        pipeline.get_state ()

        bus = pipeline.get_bus ()

        #get snapshot
        self.getShot = True
        while self.getShot:
            msg = bus.poll (gst.MESSAGE_ANY, gst.SECOND)
            if not msg:
                break

        pipeline.set_state (gst.STATE_NULL)


    def scaleto (self, size_max, width, height):
        if width > height:
            a = float(height)/width
            width = size_max
            height = int(width * a)
        else:
            a = float(width)/height
            height = size_max
            width = int(height * a)
        return (width, height)


    def snapshot_handoff_cb (self, sink, buffer, pad):
        if  self.getShot:
            caps = sink.sink_pads().next().get_negotiated_caps()
            for s in caps:
                input_d = (s['width'], s['height'])
                output_d = self.scaleto (default_width, s['width'], s['height'])
            img = Image.fromstring('RGB',input_d,buffer)
            img = img.resize(output_d, Image.BICUBIC)
            img.save(self.png_frame)
            self.getShot=False

def snapshot_mplayer(source, png_frame, timestamp):
    framedir = os.tempnam()
    os.mkdir(framedir)
    os.chdir(framedir)
    cmd = "mplayer -vo png:z=6 -vf scale -zoom -xy %d -ao null -ss '%s' -frames 2 \"%s\" >/dev/null 2>&1" % (default_width, timestamp, source)
    os.system (cmd)
    files = os.listdir(framedir)
    os.rename(os.path.join(framedir,files[-1]), png_frame)
    shutil.rmtree(framedir)

def snapshot (source, png_frame, timestamp):
    snapshot_gst (source, png_frame, timestamp)

class Frame(object):

    def __init__(self, source, timestamp, png_frame):
        snapshot (source, png_frame, timestamp)
        self.png_frame = png_frame

    def content_type (self):
        return 'image/png'

    def last_modified(self):
        source = self.inspector.ixi2source(self.ixi)
        s = os.stat(source)
        return epoch2httpdate(s.st_mtime)
  
    def __str__(self):
  
        f = open(self.png_frame,'rb')
        i = f.read()
        f.close()
  
        return i
